class Automata
    attr_accessor :nodes, :start_node

    def initialize(nodes, start_node)
        @nodes = nodes
        @start_node = start_node
    end

    def print(filename)
        file = File.new(filename, "w")
        file.puts("digraph G {")
        file.puts("    rankdir=LR;")
        file.puts("    size=\"8,5\"")

        for node in @nodes
            if node.final?
                file.puts("    node [shape = doublecircle]; ")
                file.puts("    S_" + node.name)
            else
                file.puts("    node [shape = circle]; ")
                file.puts("    S_" + node.name)
            end
        end

        for node in @nodes
            for neighbour, term in node.neighbours
                edge = if term then term.name else "epsilon" end
                file.puts("    S_#{node.name} -> S_#{neighbour.name} [ label = \"#{edge}\" ];")
            end
        end

        file.puts("}")
        file.close
    end

    def parse(str)
        @start_node.parse str
    end
end

class AutomataNode
    attr_accessor :nonterm, :final
    attr_reader :name, :neighbours

    def initialize(name)
        @neighbours = [] # [[neighbour, term]]
        @final = false
        @nonterm = nil
        @name = name
    end

    def final?
        final
    end

    def add_edge(node, term = nil)
        @neighbours << [node, term]
    end


    def parse(str)
        if @final 
            if str.size == 0
                return true
            end
        end
        for neighbour, term in @neighbours
            if term == nil
                if neighbour.parse(str)
                    return true
                end
            elsif str[0, 1] == term.name
                if neighbour.parse(str[1..-1])
                    return true
                end
            end
        end
        return false
    end
end

